package jp.co.katagaki.crossword.io.reader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import au.com.bytecode.opencsv.CSVParser;
import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;
import au.com.bytecode.opencsv.bean.ColumnPositionMappingStrategy;
import au.com.bytecode.opencsv.bean.CsvToBean;

import jp.co.katagaki.crossword.io.resolver.PuzzleWordResolver;
import jp.co.katagaki.crossword.puzzle.Word;
import jp.co.katagaki.util.ArrayUtil;

/**
 * {@link PuzzleWordReader}の{@link CSVReader}実装クラス。
 *
 * @author naotake
 */
public class PuzzleWordCsvReader implements PuzzleWordReader {

    private String fileName;
    private PuzzleWordResolver wordResolver;
    private List<Word> wordList;

    /**
     * 指定されたファイル名を基にインスタンスを生成する。
     *
     * @param fileName
     *            ファイル名
     * @param wordResolver
     *            単語リゾルバー
     */
    public PuzzleWordCsvReader(String fileName, PuzzleWordResolver wordResolver) {
        this.fileName = fileName;
        this.wordResolver = wordResolver;
        initialize();
    }

    private void initialize() {
        String pathName = "/"
                + StringUtils.replace(PuzzleWordCsvReader.class.getPackage()
                        .getName(), ".", "/") + "/" + fileName;
        URL url = PuzzleWordReader.class.getResource(pathName);
        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(new File(url.toURI())),
                    CSVParser.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER);
        } catch (FileNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        } catch (URISyntaxException e) {
            throw new ExceptionInInitializerError(e);
        }

        ColumnPositionMappingStrategy<Word> mappingStrategy = new ColumnPositionMappingStrategy<Word>();
        mappingStrategy.setType(Word.class);
        mappingStrategy.setColumnMapping(ArrayUtil.toArray(wordResolver
                .resolvePropertiesWord()));
        CsvToBean<Word> csvToBean = new CsvToBean<Word>();
        wordList = csvToBean.parse(mappingStrategy, reader);
    }

    @Override
    public List<Word> readAll() {
        return wordList;
    }
}
